# -*- coding: utf-8 -*-
# @Time    : 2024/4/22 16:30
# @Author  : Jonny
# @File    : LuckMain.py
# @Describe: 告警入口

from flask import Flask, request, jsonify
from flask_basicauth import BasicAuth
from apscheduler.schedulers.background import BackgroundScheduler
import json
import os
from logging.handlers import TimedRotatingFileHandler
import logging
from datetime import datetime
import base64
from luck.core.LuckConstant import LuckConstant
from luck.util.LuckLogHelperUtils import LuckLogHelperUtils
from luck.ai.LuckGitlabCodeReviewMain import luck_gitlab_ai_bp
from luck.gitlab.LuckGitlabLogMain import luck_gitlab_log_bp
from luck.gitlab.LuckGitlabUserMain import luck_gitlab_user_bp
from luck.gitlab.LuckGitlabProjectMain import luck_gitlab_project_bp

scheduler = BackgroundScheduler()
# 创建Flask应用实例
app = Flask(__name__)

# 解决中文乱码问题
try:
    app.json.ensure_ascii = False
except Exception:
    app.ensure_ascii = False

# 获取当前脚本的路径
script_dir = os.path.dirname(os.path.abspath(__file__))  # 项目工程路径/luck

# 如果works/logs文件夹不存在则创建
if not os.path.exists(os.path.join(script_dir, LuckConstant.LOG_DIR)):
    os.makedirs(os.path.join(script_dir, LuckConstant.LOG_DIR))

app.config['LOG_FILE'] = os.path.join(script_dir, LuckConstant.LOG_DIR, LuckConstant.LOG_FILE)  # 修改log文件路径到logs文件夹下
app.config['LOG_LEVEL'] = logging.INFO
app.config['LOG_FORMAT'] = '%(asctime)s %(levelname)s: %(message)s'

# 配置全局日志
LOG_FILE = app.config['LOG_FILE']
LOG_LEVEL = app.config['LOG_LEVEL']
LOG_FORMAT = app.config['LOG_FORMAT']

# 设置日志格式
formatter = logging.Formatter(LOG_FORMAT)

# 设置日志处理器，按天生成日志文件
handler = TimedRotatingFileHandler(LOG_FILE, when="midnight", interval=1, backupCount=3)  # 每天生成一个新的日志文件，保留最近3天的日志文件
handler.setFormatter(formatter)  # 设置日志格式
handler.setLevel(LOG_LEVEL)  # 设置日志级别

# 创建并配置logger对象
logger = logging.getLogger()  # 获取root logger对象
logger.setLevel(LOG_LEVEL)  # 设置root logger的日志级别
logger.addHandler(handler)  # 添加handler到root logger对象中

# 创建一个handler，用于写入日志到控制台
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)  # 也可以为handler单独设置级别

# 创建一个日志格式器，并将其添加到handler中
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
console_handler.setFormatter(formatter)

# 将handler添加到logger中
logger.addHandler(console_handler)
logger.info('Start of the program')  # 输出一条info级别的日志，用于测试日志功能是否正常开启

global config

# 从环境变量中读取参数
server_port = os.getenv("SERVER_PORT")
if server_port is not None and server_port != '':
    config = {
        "server_port": int(server_port),

        "agent_id": os.getenv("AGENT_ID"),
        "app_key": os.getenv("APP_KEY"),
        "app_secret": os.getenv("APP_SECRET"),

        "dingtalk_app_key": os.getenv("DINGTALK_APP_KEY"),
        "dingtalk_app_secret": os.getenv("DINGTALK_APP_SECRET"),
        "dingtalk_url": os.getenv("DINGTALK_URL"),
        "dingtalk_url_basic_auth1": os.getenv("DINGTALK_URL_BASIC_AUTH1"),
        "dingtalk_url_basic_auth2": os.getenv("DINGTALK_URL_BASIC_AUTH2"),

        "log_app_key": os.getenv("LOG_APP_KEY"),
        "log_app_secret": os.getenv("LOG_APP_SECRET"),
        "log_url": os.getenv("LOG_URL"),
        "log_url_basic_auth1": os.getenv("LOG_URL_BASIC_AUTH1"),
        "log_url_basic_auth2": os.getenv("LOG_URL_BASIC_AUTH2"),

        "db_type": os.getenv("DB_TYPE"),
        "db_host": os.getenv("DB_HOST"),
        "db_port": int(os.getenv("DB_PORT")),
        "db_name": os.getenv("DB_NAME"),
        "db_user": os.getenv("DB_USER"),
        "db_password": os.getenv("DB_PASSWORD"),

        "gitlab_private_token": os.getenv("GITLAB_PRIVATE_TOKEN"),
        "gitlab_server_url": os.getenv("GITLAB_SERVER_URL")
    }
    # 认证鉴权
    basic_auth1 = os.getenv("BASIC_AUTH1")
    if basic_auth1 is None or len(basic_auth1) <= 0:
        basic_auth1 = "admin"
    config["basic_auth1"] = basic_auth1

    basic_auth2 = os.getenv("BASIC_AUTH2")
    if basic_auth2 is None or len(basic_auth2) <= 0:
        basic_auth2 = "luckserver"
    config["basic_auth2"] = basic_auth2
else:
    filename = os.path.join(script_dir, LuckConstant.CONFIG_FILE)
    with open(filename, "r", encoding="utf-8") as fp:
        json_str = fp.read().strip()
        if json_str is not None and len(json_str) > 0:
            config = json.loads(json_str)
            # 认证鉴权
            basic_auth1 = config["basic_auth1"]
            if basic_auth1 is None or len(basic_auth1) <= 0:
                basic_auth1 = "admin"
            config["basic_auth1"] = basic_auth1

            basic_auth2 = config["basic_auth2"]
            if basic_auth2 is None or len(basic_auth2) <= 0:
                basic_auth2 = "luckserver"
            config["basic_auth2"] = basic_auth2

# 基本认证鉴权
app.config['BASIC_AUTH_USERNAME'] = config["basic_auth1"]
app.config['BASIC_AUTH_PASSWORD'] = config["basic_auth2"]
app.config['BASIC_AUTH_FORCE'] = True  # 为True 就默认对所有 api 进行认证， 如果设置为 False， 那么可以通过 @basic_auth.required 对指定 api 进行认证。
basic_auth = BasicAuth(app)

# 将配置数据存储在应用程序的配置对象中
app.config['CONFIG_DATA'] = config
# 注册 Blueprint
app.register_blueprint(luck_gitlab_ai_bp)
app.register_blueprint(luck_gitlab_log_bp)
app.register_blueprint(luck_gitlab_user_bp)
app.register_blueprint(luck_gitlab_project_bp)

IGNORE_URL = ["/", "/favicon.ico"]


@app.before_request
def before_request():
    if request.method != 'OPTIONS':
        # 添加访问日志
        log = LuckLogHelperUtils(config)
        log.add_visit_log({
            "requri": request.path,
            "reqtype": request.method,
            "reqmethod": request.method,
            "reqparam": "",
            "reqnote": ""
        })


# 错误处理器：记录异常信息
@app.errorhandler(Exception)
def log_exception(error):
    if request.method != 'OPTIONS':
        # 添加访问日志
        log = LuckLogHelperUtils(config)
        log.add_error_log({
            "requri": request.path,
            "reqtype": request.mimetype,
            "reqmethod": request.method,
            "reqparam": "",
            "reqnote": "",
            "reqerror": str(error)
        })
        return jsonify({'error': '服务内部错误'}), 500


# 检查服务状态
@app.route('/')
def index():
    print(f'小程序 于 {datetime.now().strftime("%Y-%m-%d %H:%M:%S")} 查看 gitlab服务部署状态')

    return {
        "code": LuckConstant.CODE_SUCCESS,
        "data": [
            "/",
            "/gitlab/ai",
            "/gitlab/log",
            "/gitlab/user",
            "/gitlab/project"
        ],
        "msg": "gitlab服务部署成功"
    }
def job_read_user_data():
    with app.test_client() as client:
        auth = str(base64.b64encode(f'{config["basic_auth1"]}:{config["basic_auth2"]}'.encode('utf-8')), 'utf-8')
        headers = {
            'Content-Type': 'application/json',
            'Authorization': f'Basic {auth}'
        }
        data = {
            "log_app_key": config["log_app_key"],
            "log_app_secret": config["log_app_secret"]
        }
        response = client.get('/gitlab/user/readUserData', data=json.dumps(data), headers=headers)
        # 处理响应，例如打印状态码
        print(f"/gitlab/user/readUserData API call response status: {response.status_code}")

def job_read_commit_data():
    with app.test_client() as client:
        auth = str(base64.b64encode(f'{config["basic_auth1"]}:{config["basic_auth2"]}'.encode('utf-8')), 'utf-8')
        headers = {
            'Content-Type': 'application/json',
            'Authorization': f'Basic {auth}'
        }
        data = {
            "log_app_key": config["log_app_key"],
            "log_app_secret": config["log_app_secret"]
        }
        response = client.get('/gitlab/log/readCommitData?day_num=1', data=json.dumps(data), headers=headers)
        # 处理响应，例如打印状态码
        print(f"/gitlab/log/readCommitData API call response status: {response.status_code}")

def job_read_project_data():
    with app.test_client() as client:
        auth = str(base64.b64encode(f'{config["basic_auth1"]}:{config["basic_auth2"]}'.encode('utf-8')), 'utf-8')
        headers = {
            'Content-Type': 'application/json',
            'Authorization': f'Basic {auth}'
        }
        data = {
            "log_app_key": config["log_app_key"],
            "log_app_secret": config["log_app_secret"]
        }
        response = client.get('/gitlab/project/readProjectData', data=json.dumps(data), headers=headers)
        # 处理响应，例如打印状态码
        print(f"/gitlab/project/readProjectData API call response status: {response.status_code}")


scheduler.add_job(job_read_user_data, 'cron', hour=22)
scheduler.add_job(job_read_commit_data, 'cron', hour="*/4")
scheduler.add_job(job_read_project_data, 'cron', hour=23)
scheduler.start()

def main():
    app.run(debug=False, use_reloader=False, host='0.0.0.0', port=config["server_port"])
